/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = frstat_pkg.c                                       */
/*  NOTE      =                                                    */
/*  DATE      = 2015/05/26 by yaohl                                */
/*******************************************************************/
#include <stdio.h>
#include <string.h>
#include <sys/time.h>
#include <pthread.h>
#include <json-c/json.h>

#include "frcomm.h"
#include "frlog.h"

typedef struct __st_stat_pkg {
    unsigned long ul_pkg_if_rcv;      //设备接到的包数(包括丢弃的包)
    unsigned long ul_pkg_if_drop;     //设备丢弃的包数

    unsigned long ul_pkg_pcap_rcv;    //libpcap接到的包数
    //unsigned long ul_pkg_pcap_drop;   //libpcap丢弃的包数

    //框架接到的数据包:st_stat_pkg_frame_drop+st_stat_pkg_frame_udp+st_stat_pkg_frame_tcp
    unsigned long ul_pkg_frame_drop;  //框架丢弃的包数

    unsigned long ul_pkg_frame_udp;   //框架接到的udp数据包(不包括丢弃的包)
    unsigned long ul_pkg_frame_tcp;   //框架接到的tcp数据包(不包括丢弃的包, 包括st_stat_pkg_frame_syn,st_stat_pkg_frame_fin)
    unsigned long ul_pkg_frame_syn;
    unsigned long ul_pkg_frame_fin;
} frStatPkg;

typedef struct __st_stat_count {
    unsigned long ul_pkg_if_rcv;
    unsigned long ul_pkg_if_drop;

    unsigned long ul_pkg_pcap_rcv;
    unsigned long ul_pkg_pcap_drop;

    unsigned long ul_pkg_frame_rcv;     //框架接到的数据包:ul_pkg_frame_drop+ul_pkg_frame_udp+ul_pkg_frame_tcp
    unsigned long ul_pkg_frame_drop;

    unsigned long ul_pkg_frame_udp;
    unsigned long ul_pkg_frame_tcp;
    unsigned long ul_pkg_frame_syn;
    unsigned long ul_pkg_frame_fin;
} frstatCount;

FR_STATIC pthread_spinlock_t   g_spin_lock;
FR_STATIC frStatPkg g_st_stat_pkg_now, g_st_stat_pkg_last;
FR_STATIC frstatCount g_st_stat_count;

/*******************************************************************************
*  FUNC     :  统计设备上收到包的数量
*  ARGS     :
*  RTN      :
*  NOTE     :
*******************************************************************************/
void frstat_pkg_add_if_rcv(unsigned long ul_pkg_cnt)
{
    pthread_spin_lock(&g_spin_lock);
    g_st_stat_pkg_now.ul_pkg_if_rcv = ul_pkg_cnt;
    pthread_spin_unlock(&g_spin_lock);
    return;
}

/*******************************************************************************
*  FUNC     :  统计设备上丢弃包的数量
*  ARGS     :
*  RTN      :
*  NOTE     :
*******************************************************************************/
void frstat_pkg_add_if_drop(unsigned long ul_pkg_cnt)
{
    pthread_spin_lock(&g_spin_lock);
    g_st_stat_pkg_now.ul_pkg_if_drop = ul_pkg_cnt;
    pthread_spin_unlock(&g_spin_lock);
    return;
}


/*******************************************************************************
*  FUNC     :  统计libpcap上收到包的数量
*  ARGS     :
*  RTN      :
*  NOTE     :
*******************************************************************************/
void frstat_pkg_add_pcap_rcv(unsigned long ul_pkg_cnt)
{
    pthread_spin_lock(&g_spin_lock);
    g_st_stat_pkg_now.ul_pkg_pcap_rcv = ul_pkg_cnt;
    pthread_spin_unlock(&g_spin_lock);
    return;
}

/*******************************************************************************
*  FUNC     :  统计libpcap上丢弃包的数量
*  ARGS     :
*  RTN      :
*  NOTE     :
*******************************************************************************/
//void frstat_pkg_add_pcap_drop(unsigned long ul_pkg_cnt)
//{
//    //pthread_spin_lock(&g_spin_lock);
//    //g_st_stat_pkg_now.ul_pkg_pcap_drop = ul_pkg_cnt;
//    //pthread_spin_unlock(&g_spin_lock);
//    return;
//}

/*******************************************************************************
*  FUNC     :  统计框架丢弃包的数量
*  ARGS     :
*  RTN      :
*  NOTE     :
*******************************************************************************/
void frstat_pkg_add_frame_drop(unsigned long ul_pkg_cnt)
{
    if(ul_pkg_cnt > 0)
    {
        pthread_spin_lock(&g_spin_lock);
        g_st_stat_pkg_now.ul_pkg_frame_drop += ul_pkg_cnt;
        pthread_spin_unlock(&g_spin_lock);
    }
    return;
}

/*******************************************************************************
*  FUNC     :  统计框架(udp)收到包的数量
*  ARGS     :
*  RTN      :
*  NOTE     :
*******************************************************************************/
void frstat_pkg_add_frame_udp(unsigned long ul_pkg_cnt)
{
    if(ul_pkg_cnt > 0)
    {
        pthread_spin_lock(&g_spin_lock);
        g_st_stat_pkg_now.ul_pkg_frame_udp += ul_pkg_cnt;
        pthread_spin_unlock(&g_spin_lock);
    }
    return;
}

/*******************************************************************************
*  FUNC     :  统计框架(tcp)收到包的数量
*  ARGS     :
*  RTN      :
*  NOTE     :
*******************************************************************************/
void frstat_pkg_add_frame_tcp(unsigned long ul_pkg_cnt)
{
    if(ul_pkg_cnt > 0)
    {
        pthread_spin_lock(&g_spin_lock);
        g_st_stat_pkg_now.ul_pkg_frame_tcp += ul_pkg_cnt;
        pthread_spin_unlock(&g_spin_lock);
    }
    return;
}

/*******************************************************************************
*  FUNC     :  统计框架(syn)收到包的数量
*  ARGS     :
*  RTN      :
*  NOTE     :
*******************************************************************************/
void frstat_pkg_add_frame_syn(unsigned long ul_pkg_cnt)
{
    if(ul_pkg_cnt > 0)
    {
        pthread_spin_lock(&g_spin_lock);
        g_st_stat_pkg_now.ul_pkg_frame_syn += ul_pkg_cnt;
        g_st_stat_pkg_now.ul_pkg_frame_tcp += ul_pkg_cnt;
        pthread_spin_unlock(&g_spin_lock);
    }
    return;
}

/*******************************************************************************
*  FUNC     :  统计框架(fin)收到包的数量
*  ARGS     :
*  RTN      :
*  NOTE     :
*******************************************************************************/
void frstat_pkg_add_frame_fin(unsigned long ul_pkg_cnt)
{
    if(ul_pkg_cnt > 0)
    {
        pthread_spin_lock(&g_spin_lock);
        g_st_stat_pkg_now.ul_pkg_frame_fin += ul_pkg_cnt;
        g_st_stat_pkg_now.ul_pkg_frame_tcp += ul_pkg_cnt;
        pthread_spin_unlock(&g_spin_lock);
    }
    return;
}

/*******************************************************************************
*  FUNC     :  统计信息出力
*  ARGS     :
*  RTN      :
*  NOTE     :
*******************************************************************************/
void frstat_pkg_info(char *p_outinfo, unsigned int ui_size)
{
    unsigned long ul_pcap_rcv_all=0, ul_pcap_rcv_succ=0, ul_pcap_rcv_fail=0;
    if(p_outinfo == NULL || ui_size <= 0)
    {
        pthread_spin_lock(&g_spin_lock);

        ul_pcap_rcv_all = g_st_stat_count.ul_pkg_if_rcv - g_st_stat_count.ul_pkg_if_drop;
        if( (long)g_st_stat_count.ul_pkg_pcap_drop < 0 ) //时间差的原因,ul_pkg_pcap_rcv收到的包有可能比设备上收到的包多
        {
            ul_pcap_rcv_succ = ul_pcap_rcv_all;
            ul_pcap_rcv_fail = 0;
        }
        else
        {
            ul_pcap_rcv_succ = g_st_stat_count.ul_pkg_pcap_rcv;
            ul_pcap_rcv_fail = g_st_stat_count.ul_pkg_pcap_drop;
        }
        if(g_st_stat_count.ul_pkg_if_rcv >= g_st_stat_count.ul_pkg_if_drop
           && g_st_stat_count.ul_pkg_frame_rcv >= g_st_stat_count.ul_pkg_frame_drop
           )
            FRLOG_DEBUG("pkg_info:if_rcv:%lu(succ:%lu drop:%lu);pcap_rcv:%lu(succ:%lu drop:%lu)"
                        ";frame_rcv:%lu(succ:%lu drop:%lu) udp:%lu tcp:%lu(syn:%lu fin:%lu)"
                        , g_st_stat_count.ul_pkg_if_rcv, g_st_stat_count.ul_pkg_if_rcv - g_st_stat_count.ul_pkg_if_drop, g_st_stat_count.ul_pkg_if_drop
                        , ul_pcap_rcv_all,ul_pcap_rcv_succ, ul_pcap_rcv_fail
                        , g_st_stat_count.ul_pkg_frame_rcv, g_st_stat_count.ul_pkg_frame_rcv - g_st_stat_count.ul_pkg_frame_drop, g_st_stat_count.ul_pkg_frame_drop
                        , g_st_stat_count.ul_pkg_frame_udp, g_st_stat_count.ul_pkg_frame_tcp, g_st_stat_count.ul_pkg_frame_syn, g_st_stat_count.ul_pkg_frame_fin);

        pthread_spin_unlock(&g_spin_lock);
        return;
    }

    pthread_spin_lock(&g_spin_lock);

    ul_pcap_rcv_all = g_st_stat_count.ul_pkg_if_rcv - g_st_stat_count.ul_pkg_if_drop;
    if( (long)g_st_stat_count.ul_pkg_pcap_drop < 0 )
    {
        ul_pcap_rcv_succ = ul_pcap_rcv_all;
        ul_pcap_rcv_fail = 0;
    }
    else
    {
        ul_pcap_rcv_succ = g_st_stat_count.ul_pkg_pcap_rcv;
        ul_pcap_rcv_fail = g_st_stat_count.ul_pkg_pcap_drop;
    }

    if(g_st_stat_count.ul_pkg_if_rcv >= g_st_stat_count.ul_pkg_if_drop
       && g_st_stat_count.ul_pkg_frame_rcv >= g_st_stat_count.ul_pkg_frame_drop
       )
        snprintf(p_outinfo, ui_size, "packet info:\n\tif_rcv:%lu(succ:%lu drop:%lu)\n\tpcap_rcv:%lu(succ:%lu drop:%lu)"
                    "\n\tframe_rcv:%lu(succ:%lu drop:%lu) udp:%lu tcp:%lu(syn:%lu fin:%lu)\n"
                , g_st_stat_count.ul_pkg_if_rcv, g_st_stat_count.ul_pkg_if_rcv - g_st_stat_count.ul_pkg_if_drop, g_st_stat_count.ul_pkg_if_drop
                , ul_pcap_rcv_all,ul_pcap_rcv_succ, ul_pcap_rcv_fail
                , g_st_stat_count.ul_pkg_frame_rcv, g_st_stat_count.ul_pkg_frame_rcv - g_st_stat_count.ul_pkg_frame_drop, g_st_stat_count.ul_pkg_frame_drop
                , g_st_stat_count.ul_pkg_frame_udp, g_st_stat_count.ul_pkg_frame_tcp, g_st_stat_count.ul_pkg_frame_syn, g_st_stat_count.ul_pkg_frame_fin);
    pthread_spin_unlock(&g_spin_lock);
    return;
}

/*******************************************************************************
*  FUNC     :  包信息统计
*  ARGS     :
*  RTN      :
*  NOTE     :
*******************************************************************************/
void frstat_pkg_count(void)
{
    pthread_spin_lock(&g_spin_lock);

    g_st_stat_count.ul_pkg_if_rcv = g_st_stat_pkg_now.ul_pkg_if_rcv - g_st_stat_pkg_last.ul_pkg_if_rcv;
    g_st_stat_count.ul_pkg_if_drop = g_st_stat_pkg_now.ul_pkg_if_drop - g_st_stat_pkg_last.ul_pkg_if_drop;
    g_st_stat_count.ul_pkg_pcap_rcv = g_st_stat_pkg_now.ul_pkg_pcap_rcv - g_st_stat_pkg_last.ul_pkg_pcap_rcv;
    //g_st_stat_count.ul_pkg_pcap_drop = g_st_stat_pkg_now.ul_pkg_pcap_drop - g_st_stat_pkg_last.ul_pkg_pcap_drop;
    g_st_stat_count.ul_pkg_pcap_drop = g_st_stat_count.ul_pkg_if_rcv - g_st_stat_count.ul_pkg_if_drop - g_st_stat_count.ul_pkg_pcap_rcv;

    g_st_stat_count.ul_pkg_frame_drop = g_st_stat_pkg_now.ul_pkg_frame_drop - g_st_stat_pkg_last.ul_pkg_frame_drop;
    g_st_stat_count.ul_pkg_frame_udp = g_st_stat_pkg_now.ul_pkg_frame_udp - g_st_stat_pkg_last.ul_pkg_frame_udp;
    g_st_stat_count.ul_pkg_frame_tcp = g_st_stat_pkg_now.ul_pkg_frame_tcp - g_st_stat_pkg_last.ul_pkg_frame_tcp;
    g_st_stat_count.ul_pkg_frame_syn = g_st_stat_pkg_now.ul_pkg_frame_syn - g_st_stat_pkg_last.ul_pkg_frame_syn;
    g_st_stat_count.ul_pkg_frame_fin = g_st_stat_pkg_now.ul_pkg_frame_fin - g_st_stat_pkg_last.ul_pkg_frame_fin;
    g_st_stat_count.ul_pkg_frame_rcv = g_st_stat_count.ul_pkg_frame_drop + g_st_stat_count.ul_pkg_frame_udp + g_st_stat_count.ul_pkg_frame_tcp;

    memcpy(&g_st_stat_pkg_last, &g_st_stat_pkg_now, sizeof(frStatPkg));

    pthread_spin_unlock(&g_spin_lock);

    frstat_pkg_info(NULL, 0);
    return;
}


/*******************************************************************************
*  FUNC     :  包信息统计
*  ARGS     :
*  RTN      :
*  NOTE     :
*******************************************************************************/
void frstat_pkg_count_json(json_object *p_st_json)
{
    json_object *p_st_json_sub;
    long l_Drop=0;
    if(p_st_json == NULL)
        return;

    p_st_json_sub = p_st_json_sub = json_object_new_object();
    if(p_st_json_sub == NULL)
        return;

    pthread_spin_lock(&g_spin_lock);

    if(g_st_stat_pkg_now.ul_pkg_if_rcv - g_st_stat_pkg_now.ul_pkg_if_drop > 0)
        json_object_object_add(p_st_json_sub, "ifRX", json_object_new_int64( g_st_stat_pkg_now.ul_pkg_if_rcv - g_st_stat_pkg_now.ul_pkg_if_drop) );
    else
        json_object_object_add(p_st_json_sub, "ifRX", json_object_new_int64( 0 ) );
    json_object_object_add(p_st_json_sub, "ifDrop", json_object_new_int64( g_st_stat_pkg_now.ul_pkg_if_drop ));
    json_object_object_add(p_st_json_sub, "pcapRX", json_object_new_int64( g_st_stat_pkg_now.ul_pkg_pcap_rcv ));
    l_Drop = g_st_stat_pkg_now.ul_pkg_if_rcv - g_st_stat_pkg_now.ul_pkg_if_drop - g_st_stat_pkg_now.ul_pkg_pcap_rcv;
    if(l_Drop > 0)
        l_Drop = 0;
    json_object_object_add(p_st_json_sub, "pcapDrop", json_object_new_int64( l_Drop ));
    json_object_object_add(p_st_json_sub, "frameRX", json_object_new_int64( g_st_stat_pkg_now.ul_pkg_frame_tcp + g_st_stat_pkg_now.ul_pkg_frame_udp ));
    json_object_object_add(p_st_json_sub, "frameDrop", json_object_new_int64( g_st_stat_pkg_now.ul_pkg_frame_drop ));

    pthread_spin_unlock(&g_spin_lock);

    json_object_object_add(p_st_json, "packet", p_st_json_sub);

    return;
}

/*******************************************************************************
*  FUNC     :  初始化数据包统计
*  ARGS     :
*  RTN      :  FR_SUCC   (成功)
*              FR_FAIL   (失败)
*  NOTE     :
*******************************************************************************/
int  frstat_pkg_init(void)
{
    pthread_spin_init(&g_spin_lock, 0);
    memset(&g_st_stat_pkg_now, 0x00, sizeof(frStatPkg));
    memset(&g_st_stat_pkg_last, 0x00, sizeof(frStatPkg));

    memset(&g_st_stat_count, 0x00, sizeof(frstatCount));
    return FR_SUCC;
}

/*******************************************************************************
*  FUNC     :  退出数据包统计
*  ARGS     :
*  RTN      :
*  NOTE     :
*******************************************************************************/
void frstat_pkg_destory(void)
{
    pthread_spin_destroy(&g_spin_lock);
    return;
}

